import os
import importlib.util

root_path = os.path.realpath(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))


def get_func(path, func_name):
    '''
    function: 根据路径获取文件中的类方法
    :param path:
    :param func_name:
    :return:
    '''
    if not os.path.isfile(path):
        raise IOError
    # 根据提供的目标文件路径，返回模块的说明  spec_from_file_location(module_name, file_path)
    module_desc = importlib.util.spec_from_file_location("_", path)
    # 根据传入的模块说明返回引入的模块 module_from_spec（模块说明）
    moudle_spec = importlib.util.module_from_spec(module_desc)
    # exec_module执行加载方法
    module_desc.loader.exec_module(moudle_spec)
    if hasattr(moudle_spec, func_name):
        return getattr(moudle_spec, func_name)


class GetSimilarityName:
    def __init__(self):
        '''
        function: 搜索算子中含有operator名称的算子，并获取其中的类方法
        :param className:
        '''
        self.operatordirectory = os.path.join(root_path, 'Measure/similarity')
        # 搜索所有路径
        self.pathResult = self.DFS_file_search()

    def DFS_file_search(self):
        '''
        function: 获取该文件夹及其子文件中的所有问价的绝对路径
        :return: 绝对路径列表
        '''
        stack = []
        result_txt = []
        stack.append(self.operatordirectory)
        while len(stack) != 0:  # 栈空代表所有目录均已完成访问
            temp_name = stack.pop()
            try:
                temp_name2 = os.listdir(temp_name)  # list ["","",...]
                for eve in temp_name2:
                    stack.append(temp_name + "\\" + eve)  # 维持绝对路径的表达
            except NotADirectoryError:
                if '__pycache__' in temp_name:
                    continue
                result_txt.append(temp_name)
        return result_txt

    def getClass(self, lis):
        '''
        functioh: 用来检验类中是否存在getResult方法
        :param list: 存储文件路径与类名的一个向量
        :return:
        '''
        length = len(lis)
        for i in range(length):
            temp = lis[i]
            li = []
            for j in temp[2]:
                func = get_func(temp[1], j)
                # print(func,temp)
                if func == None:
                    continue
                if func.__dict__.get('getSimilarity') != None:
                    li.append(func)

            lis[i][2] = li
        return lis

    def getResult(self):
        '''
        function: 对得到的文件路径进行处理，获得算子文件中所有的类名
        :return: 文件名与类对应的字典
        '''
        # 存储算子路径
        file_name = []
        # 存储结果
        result = []
        # 筛选含有算子名的绝对路径
        for i in self.pathResult:
            if '.py' in i:
                file_name.append(i)
        for i in range(len(file_name)):
            f = open(file_name[i], 'r', encoding="utf-8")
            data = f.readlines()
            # 遍历行获取类名
            li = []
            for j in data:
                if 'class' in j:
                    temp = ''
                    for k in j[6:]:
                        if k == '(':
                            break
                        temp += k
                    li.append(temp)
            lis = file_name[i].split('\\')
            temp = [lis[-1][:-3], file_name[i], li]
            result.append(temp)
        result = self.getClass(result)
        # dictory_result={}
        # for i in result:
        #     dictory_result[i[0]]=
        return result

    def getname(self):
        """
        function: 获取算子名称的名称
        :return: 算子名称
        """
        temp = self.getResult()
        pathdictory = {}
        for i in temp:
            # pathdictory[i[0]]=i[1]
            flag = False
            path = ''
            for t in i[1].split("\\"):
                if t == 'DecisionSystem':
                    flag = True
                    continue
                if flag == True:
                    path = os.path.join(path, t)
            pathdictory[i[0]] = path
        return pathdictory



if __name__ == '__main__':
    # print(root_path)
    example = GetSimilarityName()
    # 获得算子名称example.GetOperatorName()
    for i in (example.getname()):
        print(i)
